#include <stdio.h>
#include <stdlib.h>
#include "LinkList.h"

//自定义节点
typedef struct {
	LIST_NODE node;		//第一项必须是 LIST_NODE类型的变量 
	int a; 				//后边可以添加其他类型成员 
} myNode;

int scoreCompare(const LIST_NODE *node1, const LIST_NODE *node2)
{
	//比较任何你想比较的结构体成员 
	return ((myNode*)node1)->a - ((myNode*)node2)->a;	
}  

int main(void)
{
//初始化测试	
	LIST_MANAGE listManage;			//定义链表管理器变量 
	ListManageInit(&listManage);	//初始化
	
	myNode* node1 = (myNode*)malloc(sizeof(myNode));
	node1->a = 1; 
	myNode* node2 = (myNode*)malloc(sizeof(myNode));
	node2->a = 2;
	myNode* node3 = (myNode*)malloc(sizeof(myNode));
	node3->a = 3;
	myNode* node4 = (myNode*)malloc(sizeof(myNode));
	node4->a = 4;

//插入测试	
	//函数参数类型是LIST_NODE*，而本程序变量类型是myNode
	//可以通过强制转换来传入，例如(LIST_NODE*)node1
	//也可以获取变量的node成员地址方式来传入，例如&(node1->node)
	ListPutTail(&listManage, (LIST_NODE*)node1); 					//插入到链表尾部 
	ListPutHead(&listManage, (LIST_NODE*)node2); 					//插入到链表头部 
	ListInsertAfterItem(&listManage, &(node1->node), (LIST_NODE*)node3);	//插入到node1之前	 
	ListInsertBeforIndex(&listManage, -1, (LIST_NODE*)node4); 		//插入到最后一个节点之前	

//遍历测试	
	myNode *pln = NULL;	
	
	printf("一、遍历测试：\r\n");
	printf("从前往后遍历：");
	//从头遍历(注意：pln类型尽量直接定义成myNode*)：
	//上边的for循环使用的是带错误判断的库函数；缺点是，格式太复杂了，需要取地址还要二级指针还要强制转换
	//第二行是不带错误判断的库函数，相对来说是形式简单
	//for (ListPeekHead(&listManage, (LIST_NODE**)&pln); pln != NULL; ListPeekNext((LIST_NODE*)pln, (LIST_NODE**)&pln)) 
	for(pln = vListPeekHead(&listManage); pln != NULL; pln = vListPeekNext((LIST_NODE*)pln))
	{
		printf("%d,",pln->a);
	}
	//从尾遍历：
	printf("从后往前遍历：");
	for(pln = vListPeekTail(&listManage); pln != NULL; pln = vListPeekPrev((LIST_NODE*)pln))
	{
		printf("%d,",pln->a);
	}    
	
	
//排序测试
	printf("\r\n二、排序测试：\r\n");
	ListSort(&listManage, true, scoreCompare);//从小到大排序
	
	printf("从小到大排序：");
	for(pln = vListPeekHead(&listManage); pln != NULL; pln = vListPeekNext((LIST_NODE*)pln))
	{
		printf("%d,",pln->a);
	} 
	
	ListSort(&listManage, false, scoreCompare);//从打到校排序 
	printf("\r\n从大到小排序：");
	for(pln = vListPeekHead(&listManage); pln != NULL; pln = vListPeekNext((LIST_NODE*)pln))
	{
		printf("%d,",pln->a);
	} 
	
	
//删除节点
	printf("\r\n三、节点删除测试：\r\n");
	myNode *pln1 = vListPopHead(&listManage);				//删除头节点 
	myNode *pln2 = vListPopIndex(&listManage,1);			//删除索引为1位置的节点
	
	//直接删除节点 node3
	//注意，node3节点其实已经被上边语句弹出到pln2指针里边了
	//故此这句话执行后，返回值是L_NOTHAVE，
	//只能执行else里边的代码
	if (ListPopItem(&listManage, (LIST_NODE*)node3) == L_OK) {	
		free(node3);  
		node3 = NULL;
	} else {
		//虽然node3被别人释放掉了，那么node3指针要自觉的变成NULL
		//否则就变成野指针
		node3 = NULL;
	}
	
	//重点！！！！删除后，如果不再使用，请务必释放空间 
	if(pln1 != NULL)
	{
		free(pln1);  
		pln1 = NULL;
	}
	if(pln2 != NULL)
	{
		free(pln2);  
		pln2 = NULL;
	}
	
	printf("剩余的数据：\r\n：");
	for(pln = vListPeekTail(&listManage); pln != NULL; pln = vListPeekPrev((LIST_NODE*)pln))
	{
		printf("%d,",pln->a);
	} 
	
	return 0;
}
